package com.ruoyi.recipes.service.impl;

import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.VideoFrameCapturer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.ruoyi.recipes.mapper.RecipesMapper;
import com.ruoyi.recipes.domain.Recipes;
import com.ruoyi.recipes.domain.Comments;
import com.ruoyi.recipes.domain.RecipeFavorites;
import com.ruoyi.recipes.domain.Users;
import com.ruoyi.recipes.service.IRecipesService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 菜谱主表Service业务层处理
 *
 * @author syy
 * @date 2025-08-13
 */
@Service
public class RecipesServiceImpl implements IRecipesService
{
    private static final Logger log = LoggerFactory.getLogger(RecipesServiceImpl.class);

    @Resource
    private RecipesMapper recipesMapper;
    @Resource
    private VideoFrameCapturer videoFrameCapturer; // 视频帧截取工具类
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    // Redis Key 前缀
    private static final String COMMENT_KEY_PREFIX = "recipe:comment:";
    private static final String COMMENT_COUNT_KEY_PREFIX = "recipe:comment_count:";
    private static final String COMMENT_LIKE_KEY_PREFIX = "comment:like:";
    private static final String COMMENT_LIKE_COUNT_KEY_PREFIX = "comment:like_count:";
    private static final String FAVORITE_KEY_PREFIX = "recipe:favorite:";
    private static final String FAVORITE_COUNT_KEY_PREFIX = "recipe:favorite_count:";

    /**
     * 查询菜谱主表
     *
     * @param id 菜谱主表主键
     * @return 菜谱主表
     */
    /**
     * 查询菜谱主表（新增浏览量+1逻辑）
     *
     * @param id 菜谱主表主键
     * @return 菜谱主表
     */
    @Override
    public Recipes selectRecipesById(Long id) {
        // 1. 先查询菜谱详情
        Recipes recipes = recipesMapper.selectRecipesById(id);
        if (recipes != null) {
            // 2. 浏览量+1（避免null，默认从0开始）
            Long newViewCount = (recipes.getViewCount() == null ? 0 : recipes.getViewCount()) + 1;
            recipes.setViewCount(newViewCount);

            // 3. 只更新浏览量字段，不影响其他字段
            Recipes updateVo = new Recipes();
            updateVo.setId(id);
            updateVo.setViewCount(newViewCount);
            recipesMapper.updateRecipes(updateVo);
        }
        return recipes;
    }

    /**
     * 查询菜谱主表列表
     *
     * @param recipes 菜谱主表
     * @return 菜谱主表
     */
    @Override
    public List<Recipes> selectRecipesList(Recipes recipes)
    {
        return recipesMapper.selectRecipesList(recipes);
    }

    /**
     * 新增菜谱主表
     *
     * @param recipes 菜谱主表
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertRecipes(Recipes recipes)
    {
        recipes.setCreateTime(DateUtils.getNowDate());
        System.out.println(recipes);
        if(recipes.getMediaType()!=null && recipes.getMediaType()==2){
            // 处理视频封面截取
            handleVideoCover(recipes);
            // 处理视频时长获取
            handleVideoDuration(recipes);
        }

        return recipesMapper.insertRecipes(recipes);
    }



    /**
     * 修改菜谱主表
     *
     * @param recipes 菜谱主表
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRecipes(Recipes recipes)
    {
        System.out.println(recipes+"-------------------");
        //修改的菜谱为视频类型才执行
        if(recipes.getMediaType()!=null && recipes.getMediaType()==2){
            // 如果视频路径有更新，重新生成封面和获取时长
            if (StringUtils.isNotEmpty(recipes.getCoverUrl())) {
                Recipes oldRecipes = selectRecipesById(recipes.getId());
                boolean needUpdate = (oldRecipes == null || !recipes.getCoverUrl().equals(oldRecipes.getCoverUrl()) ||
                        StringUtils.isEmpty(recipes.getVideoDescription()));

                if (needUpdate) {
                    handleVideoCover(recipes);
                    // 视频路径变更时重新获取时长
                    handleVideoDuration(recipes);
                }
            }

        }

        return recipesMapper.updateRecipes(recipes);

    }



    /**
     * 将物理路径转换为虚拟路径
     */
    private String convertToVirtualPath(String physicalPath) {
        String physicalPrefix = videoFrameCapturer.getUploadPhysicalPrefix();
        if (physicalPath.startsWith(physicalPrefix)) {
            String relativePath = physicalPath.substring(physicalPrefix.length());
            relativePath = relativePath.replaceFirst("^[/\\\\]?upload[/\\\\]?", "");
            return VideoFrameCapturer.VIRTUAL_PREFIX + relativePath;
        }
        return physicalPath;
    }

    /**
     * 处理视频时长获取
     */
    private void handleVideoDuration(Recipes recipes) {
        // 获取视频路径
        String videoPath = recipes.getCoverUrl();

        if (StringUtils.isNotEmpty(videoPath)) {
            try {
                // 调用工具类获取视频时长(秒)
                int duration = videoFrameCapturer.getVideoDurationByVirtualPath(videoPath);

                if (duration > 0) {
                    recipes.setVideoDuration(duration);
                    log.info("视频时长获取成功，路径：{}，时长：{}秒", videoPath, duration);
                } else {
                    // 时长获取失败时设置为0或保留原有值
                    recipes.setVideoDuration(0);
                    log.warn("视频时长获取失败，路径：{}", videoPath);
                }
            } catch (Exception e) {
                recipes.setVideoDuration(0);
                log.error("获取视频时长发生异常", e);
            }
        }
    }

    /**
     * 处理视频封面截取
     */
    private void handleVideoCover(Recipes recipes) {
        // 获取视频路径
        String videoPath = recipes.getCoverUrl();

        // 只有当视频路径存在且封面路径为空时才生成封面
        if (StringUtils.isNotEmpty(videoPath) && StringUtils.isEmpty(recipes.getVideoDescription())) {
            try {
                // 截取视频第3秒的帧作为封面（可根据需求调整时间）
                String coverPhysicalPath = videoFrameCapturer.captureFrameByVirtualPath(videoPath, 3.0, "jpg");

                if (StringUtils.isNotEmpty(coverPhysicalPath)) {
                    // 将物理路径转换为虚拟路径
                    String coverVirtualPath = convertToVirtualPath(coverPhysicalPath);
                    recipes.setVideoDescription(coverVirtualPath);
                } else {
                    // 截取失败使用默认封面
                    recipes.setVideoDescription("/profile/default/recipe_video_default.jpg");
                }
            } catch (Exception e) {
                // 异常情况下使用默认封面
                recipes.setVideoDescription("/profile/default/recipe_video_default.jpg");
                log.error("生成视频封面失败: {}", e.getMessage(), e);
            }
        }
    }

    /**
     * 批量删除菜谱主表
     *
     * @param ids 需要删除的菜谱主表主键
     * @return 结果
     */
    @Override
    public int deleteRecipesByIds(Long[] ids)
    {
        return recipesMapper.deleteRecipesByIds(ids);
    }

    /**
     * 删除菜谱主表信息
     *
     * @param id 菜谱主表主键
     * @return 结果
     */
    @Override
    public int deleteRecipesById(Long id)
    {
        return recipesMapper.deleteRecipesById(id);
    }
    
    /**
     * 添加菜谱评论
     */
    @Override
    public int addComment(Comments comments) {
        // 设置评论基本信息
        comments.setTargetType(2); // 2表示菜谱
        comments.setCreateTime(DateUtils.getNowDate());
        comments.setDel(0);
        comments.setLikeCount(0L);
        comments.setStatus(0); // 0表示待审核
        
        // 生成评论ID（使用时间戳+随机数）
        Long commentId = System.currentTimeMillis();
        comments.setId(commentId);
        
        // 1. 先保存到数据库
        int dbResult = recipesMapper.insertComment(comments);
        
        // 2. 清除Redis缓存，强制下次从数据库查询（包含用户信息）
        String commentKey = COMMENT_KEY_PREFIX + comments.getTargetId();
        String countKey = COMMENT_COUNT_KEY_PREFIX + comments.getTargetId();
        redisTemplate.delete(commentKey);
        redisTemplate.delete(countKey);
        
        return dbResult;
    }
    
    /**
     * 获取菜谱评论列表
     */
    @Override
    public List<Comments> getCommentsByRecipeId(Long recipeId) {
        String commentKey = COMMENT_KEY_PREFIX + recipeId;
        List<Object> comments = redisTemplate.opsForList().range(commentKey, 0, -1);
        
        List<Comments> result = new ArrayList<>();
        if (comments != null && !comments.isEmpty()) {
            for (Object obj : comments) {
                if (obj instanceof Comments) {
                    Comments comment = (Comments) obj;
                    // 获取评论点赞数
                    String likeCountKey = COMMENT_LIKE_COUNT_KEY_PREFIX + comment.getId();
                    Object likeCount = redisTemplate.opsForValue().get(likeCountKey);
                    if (likeCount != null) {
                        // 处理类型转换问题
                        if (likeCount instanceof Integer) {
                            comment.setLikeCount(((Integer) likeCount).longValue());
                        } else if (likeCount instanceof Long) {
                            comment.setLikeCount((Long) likeCount);
                        } else {
                            comment.setLikeCount(Long.valueOf(likeCount.toString()));
                        }
                    }
                    
                    // 如果Redis中的评论没有用户信息，从数据库补充
                    if (comment.getUsers() == null) {
                        Comments dbComment = recipesMapper.selectCommentWithUserById(comment.getId());
                        if (dbComment != null && dbComment.getUsers() != null) {
                            comment.setUsers(dbComment.getUsers());
                        }
                    }
                    
                    result.add(comment);
                }
            }
        }
        
        // 如果Redis中没有数据，从数据库查询
        if (result.isEmpty()) {
            result = recipesMapper.getRecipeComments(recipeId);

            // 将数据库数据同步到Redis
            if (!result.isEmpty()) {
                for (Comments comment : result) {
                    redisTemplate.opsForList().rightPush(commentKey, comment);
                }
                redisTemplate.expire(commentKey, 30, TimeUnit.DAYS);
            }
        }
        
        return result;
    }
    
    /**
     * 获取菜谱评论数量
     */
    @Override
    public Long getCommentCountByRecipeId(Long recipeId) {
        String countKey = COMMENT_COUNT_KEY_PREFIX + recipeId;
        Object count = redisTemplate.opsForValue().get(countKey);
        
        if (count != null) {
            // 处理类型转换问题
            if (count instanceof Integer) {
                return ((Integer) count).longValue();
            } else if (count instanceof Long) {
                return (Long) count;
            } else {
                return Long.valueOf(count.toString());
            }
        }
        
        // 如果Redis中没有数据，从数据库查询
        Long dbCount = recipesMapper.selectCommentCountByRecipeId(recipeId);
        if (dbCount != null && dbCount > 0) {
            redisTemplate.opsForValue().set(countKey, dbCount, 30, TimeUnit.DAYS);
        }
        
        return dbCount != null ? dbCount : 0L;
    }
    
    /**
     * 评论点赞/取消点赞
     */
    @Override
    public boolean toggleCommentLike(Long commentId, Long userId) {
        String likeKey = COMMENT_LIKE_KEY_PREFIX + commentId;
        String countKey = COMMENT_LIKE_COUNT_KEY_PREFIX + commentId;
        
        // 检查用户是否已点赞
        Boolean isLiked = redisTemplate.opsForSet().isMember(likeKey, userId);
        
        if (Boolean.TRUE.equals(isLiked)) {
            // 取消点赞
            redisTemplate.opsForSet().remove(likeKey, userId);
            redisTemplate.opsForValue().decrement(countKey, 1L);
            
            // 同步到数据库
            try {
                // 1. 更新评论点赞数
                Object currentCount = redisTemplate.opsForValue().get(countKey);
                if (currentCount != null) {
                    Long likeCount = currentCount instanceof Integer ? 
                        ((Integer) currentCount).longValue() : (Long) currentCount;
                    recipesMapper.updateCommentLikeCount(commentId, likeCount);
                }
                
                // 2. 删除点赞记录
                recipesMapper.deleteCommentLike(commentId, userId);
                
//                log.debug("取消点赞成功，commentId: {}, userId: {}", commentId, userId);
            } catch (Exception e) {
//                log.warn("同步取消点赞到数据库失败，commentId: {}, userId: {}, 错误: {}", commentId, userId, e.getMessage());
            }
            
            return false;
        } else {
            // 添加点赞
            redisTemplate.opsForSet().add(likeKey, userId);
            redisTemplate.opsForValue().increment(countKey, 1L);
            
            // 同步到数据库
            try {
                // 1. 更新评论点赞数
                Object currentCount = redisTemplate.opsForValue().get(countKey);
                if (currentCount != null) {
                    Long likeCount = currentCount instanceof Integer ? 
                        ((Integer) currentCount).longValue() : (Long) currentCount;
                    recipesMapper.updateCommentLikeCount(commentId, likeCount);
                }
                
                // 2. 插入点赞记录
                recipesMapper.insertCommentLike(commentId, userId);
                
//                log.debug("点赞成功，commentId: {}, userId: {}", commentId, userId);
            } catch (Exception e) {
//                log.warn("同步点赞到数据库失败，commentId: {}, userId: {}, 错误: {}", commentId, userId, e.getMessage());
            }
            
            return true;
        }
    }
    
    /**
     * 审核评论
     */
    @Override
    public int auditComment(Long commentId, Integer status) {
        // 这里可以添加数据库更新逻辑
        // 同时更新Redis中的评论状态
        String commentKey = COMMENT_KEY_PREFIX + "*"; // 需要找到对应的菜谱ID
        // 实现审核逻辑...
        return 1;
    }
    
    // ========== 收藏相关方法实现 ==========
    
    /**
     * 收藏/取消收藏菜谱
     */
    @Override
    public boolean toggleFavorite(Long recipeId, Long userId) {
        String favoriteKey = FAVORITE_KEY_PREFIX + recipeId;
        String countKey = FAVORITE_COUNT_KEY_PREFIX + recipeId;
        
        // 检查用户是否已收藏
        Boolean isFavorited = redisTemplate.opsForSet().isMember(favoriteKey, userId);
        
        if (Boolean.TRUE.equals(isFavorited)) {
            // 取消收藏
            redisTemplate.opsForSet().remove(favoriteKey, userId);
            redisTemplate.opsForValue().decrement(countKey, 1L);
            
            // 同步到数据库
            try {
                // 1. 删除收藏记录
                recipesMapper.deleteFavorite(recipeId, userId);
                
                // 2. 更新菜谱收藏数量
                Object currentCount = redisTemplate.opsForValue().get(countKey);
                if (currentCount != null) {
                    Long collectCount = currentCount instanceof Integer ? 
                        ((Integer) currentCount).longValue() : (Long) currentCount;
                    recipesMapper.updateRecipeCollectCount(recipeId, collectCount);
                }
                
                log.debug("取消收藏成功，recipeId: {}, userId: {}", recipeId, userId);
            } catch (Exception e) {
                log.warn("同步取消收藏到数据库失败，recipeId: {}, userId: {}, 错误: {}", recipeId, userId, e.getMessage());
            }
            
            return false;
        } else {
            // 添加收藏
            redisTemplate.opsForSet().add(favoriteKey, userId);
            redisTemplate.opsForValue().increment(countKey, 1L);
            
            // 同步到数据库
            try {
                // 1. 获取菜谱信息
                Recipes recipe = recipesMapper.selectRecipesById(recipeId);
                if (recipe != null) {
                    // 2. 获取用户信息（从数据库查询）
                    Users user = recipesMapper.selectUserById(userId);
                    if (user == null) {
                        // 如果用户不存在，创建一个默认用户对象
                        user = new Users();
                        user.setId(userId);
                        user.setNickname("用户" + userId);
                        user.setAvatarUrl("/profile/default/avatar.jpg");
                    }
                    
                    // 3. 插入收藏记录
                    RecipeFavorites favorite = new RecipeFavorites();
                    favorite.setRecipeId(recipeId);
                    favorite.setFavoriteCover(recipe.getCoverUrl());
                    favorite.setUserId(userId);
                    favorite.setUserAvatar(user.getAvatarUrl());
                    favorite.setCreateTime(DateUtils.getNowDate());
                    favorite.setDel(0);
                    
                    recipesMapper.insertFavorite(favorite);
                    
                    // 4. 更新菜谱收藏数量
                    Object currentCount = redisTemplate.opsForValue().get(countKey);
                    if (currentCount != null) {
                        Long collectCount = currentCount instanceof Integer ? 
                            ((Integer) currentCount).longValue() : (Long) currentCount;
                        recipesMapper.updateRecipeCollectCount(recipeId, collectCount);
                    }
                }
                
                log.debug("收藏成功，recipeId: {}, userId: {}", recipeId, userId);
            } catch (Exception e) {
                log.warn("同步收藏到数据库失败，recipeId: {}, userId: {}, 错误: {}", recipeId, userId, e.getMessage());
            }
            
            return true;
        }
    }
    
    /**
     * 获取菜谱收藏数量
     */
    @Override
    public Long getFavoriteCountByRecipeId(Long recipeId) {
        String countKey = FAVORITE_COUNT_KEY_PREFIX + recipeId;
        Object count = redisTemplate.opsForValue().get(countKey);
        
        if (count != null) {
            // 处理类型转换问题
            if (count instanceof Integer) {
                return ((Integer) count).longValue();
            } else if (count instanceof Long) {
                return (Long) count;
            } else {
                return Long.valueOf(count.toString());
            }
        }
        
        // 如果Redis中没有数据，从数据库查询
        Long dbCount = recipesMapper.selectFavoriteCountByRecipeId(recipeId);
        if (dbCount != null && dbCount > 0) {
            redisTemplate.opsForValue().set(countKey, dbCount, 30, TimeUnit.DAYS);
        }
        
        return dbCount != null ? dbCount : 0L;
    }
    
    /**
     * 获取用户收藏列表
     */
    @Override
    public List<RecipeFavorites> getFavoritesByUserId(Long userId) {
        // 直接从数据库查询，因为收藏列表通常不会太大
        return recipesMapper.selectFavoritesByUserId(userId);
    }
    
    /**
     * 检查用户是否已收藏菜谱
     */
    @Override
    public boolean checkUserFavorite(Long recipeId, Long userId) {
        String favoriteKey = FAVORITE_KEY_PREFIX + recipeId;
        
        // 先检查Redis
        Boolean isFavorited = redisTemplate.opsForSet().isMember(favoriteKey, userId);
        if (isFavorited != null) {
            return isFavorited;
        }
        
        // 如果Redis中没有数据，从数据库查询
        int count = recipesMapper.checkUserFavorite(recipeId, userId);
        boolean favorited = count > 0;
        
        // 将结果缓存到Redis
        if (favorited) {
            redisTemplate.opsForSet().add(favoriteKey, userId);
        }
        redisTemplate.expire(favoriteKey, 30, TimeUnit.DAYS);
        
        return favorited;
    }
    // ========== 推荐和标签相关方法实现 ==========



    /**
     * 根据场景标签获取菜谱列表
     */
    @Override
    public List<Recipes> selectRecipesBySceneTag(Recipes recipes) {
        return recipesMapper.selectRecipesBySceneTag(recipes);
    }
}
